<template>
  <div class="widget-form-container">
    <div v-if="!props.widgetForm.list?.length" class="form-empty">从左侧拖拽来添加字段</div>
    <el-form
      label-suffix=":"
      :size="props.widgetForm.config.size"
      :label-position="props.widgetForm.config.labelPosition"
      :label-width="`${props.widgetForm.config.labelWidth}px`"
      :hide-required-asterisk="props.widgetForm.config.hideRequiredAsterisk"
    >
      <Draggable
        class="widget-form-list"
        item-key="key"
        ghost-class="ghost"
        handle=".drag-widget"
        :animation="200"
        :group="{ name: 'people' }"
        :list="props.widgetForm.list"
        @add="handleMoveAdd"
      >
        <template #item="{ element, index }">
          <transition-group name="fade" tag="div">
            <template v-if="element.type === 'grid'">
              <el-row
                class="widget-col widget-view"
                type="flex"
                v-if="element.key"
                :key="element.key"
                :class="{ active: props.widgetFormSelect?.key === element.key }"
                :gutter="element.options.gutter ?? 0"
                :justify="element.options.justify"
                :align="element.options.align"
                @click="handleItemClick(element)"
              >
                <el-col v-for="(col, colIndex) in element.columns" :key="colIndex" :span="col.span ?? 0">
                  <Draggable
                    class="widget-col-list"
                    item-key="key"
                    ghost-class="ghost"
                    handle=".drag-widget"
                    :animation="200"
                    :group="{ name: 'people' }"
                    :no-transition-on-drag="true"
                    :list="col.list"
                    @add="event => handleColMoveAdd(event, element, colIndex)"
                  >
                    <template #item="{ element, index }">
                      <transition-group name="fade" tag="div">
                        <ElWidgetFormItem
                          v-if="element.key"
                          :key="element.key"
                          :element="element"
                          :config="props.widgetForm.config"
                          :selectWidget="props.widgetFormSelect"
                          @click.stop="handleItemClick(element)"
                          @copy="handleCopyClick(index, col.list)"
                          @delete="handleDeleteClick(index, col.list)"
                        />
                      </transition-group>
                    </template>
                  </Draggable>
                </el-col>

                <div class="widget-view-action widget-col-action" v-if="props.widgetFormSelect?.key === element.key">
                  <SvgIcon name="delete" @click.stop="handleDeleteClick(index, props.widgetForm.list)" />
                </div>
                <div class="widget-view-drag widget-col-drag" v-if="props.widgetFormSelect?.key === element.key">
                  <SvgIcon name="move" className="drag-widget" />
                </div>
              </el-row>
            </template>
            <template v-else>
              <ElWidgetFormItem
                v-if="element.key"
                :key="element.key"
                :element="element"
                :config="props.widgetForm.config"
                :selectWidget="props.widgetFormSelect"
                @click="handleItemClick(element)"
                @copy="handleCopyClick(index, props.widgetForm.list)"
                @delete="handleDeleteClick(index, props.widgetForm.list)"
              />
            </template>
          </transition-group>
        </template>
      </Draggable>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { nextTick } from 'vue';
import { v4 as uuidv4 } from 'uuid';
import Draggable from 'vuedraggable';
import ElWidgetFormItem from './ElWidgetFormItem.vue';
import SvgIcon from '@/components/SvgIcon/index.vue';
import type { PropType } from 'vue';
import type { WidgetForm } from '../config/element';

const props = defineProps({
  widgetForm: {
    type: Object as PropType<WidgetForm>,
    required: true
  },
  widgetFormSelect: Object
});

const emit = defineEmits(['update:widgetForm', 'update:widgetFormSelect']);

const handleItemClick = (row: any) => {
  emit('update:widgetFormSelect', row);
};

const handleListInsert = (key: string, list: any[], obj: any): any[] => {
  return list.reduce((acc, item) => {
    if (item.key === key) {
      acc.push(item, obj);
    } else {
      if (item.columns) {
        item.columns = item.columns.map((col: any) => ({
          ...col,
          list: handleListInsert(key, col.list, obj)
        }));
      }
      acc.push(item);
    }
    return acc;
  }, []);
};

const handleListDelete = (key: string, list: any[]): any[] => {
  return list.reduce((acc, item) => {
    if (item.key !== key) {
      if (item.columns) {
        item.columns = item.columns.map((col: any) => ({
          ...col,
          list: handleListDelete(key, col.list)
        }));
      }
      acc.push(item);
    }
    return acc;
  }, []);
};

const handleCopyClick = (index: number, list: any[]) => {
  const key = uuidv4().replaceAll('-', '');
  const oldList = JSON.parse(JSON.stringify(props.widgetForm.list));

  let copyData = {
    ...list[index],
    key,
    model: `${list[index].type}_${key}`,
    rules: list[index].rules ?? []
  };

  if (['radio', 'checkbox', 'select'].includes(list[index].type)) {
    copyData.options.options = copyData.options.options.map((item: any) => ({ ...item }));
  }

  emit('update:widgetForm', {
    ...props.widgetForm,
    list: handleListInsert(list[index].key, oldList, copyData)
  });

  emit('update:widgetFormSelect', copyData);
};

const handleDeleteClick = (index: number, list: any[]) => {
  const oldList = JSON.parse(JSON.stringify(props.widgetForm.list));

  if (list.length - 1 === index) {
    nextTick(() => emit('update:widgetFormSelect', list[index - 1] || null));
  } else {
    emit('update:widgetFormSelect', list[index + 1]);
  }

  emit('update:widgetForm', {
    ...props.widgetForm,
    list: handleListDelete(list[index].key, oldList)
  });
};

const handleMoveAdd = (event: any) => {
  const { newIndex } = event;
  const list = JSON.parse(JSON.stringify(props.widgetForm.list));
  const key = uuidv4().replaceAll('-', '');

  list[newIndex] = {
    ...list[newIndex],
    key,
    model: `${list[newIndex].type}_${key}`,
    rules: []
  };

  if (['radio', 'checkbox', 'select'].includes(list[newIndex].type)) {
    list[newIndex].options.options = list[newIndex].options.options.map((item: any) => ({ ...item }));
  }

  if (list[newIndex].type === 'grid') {
    list[newIndex].columns = list[newIndex].columns.map((col: any) => ({ ...col }));
  }

  emit('update:widgetForm', { ...props.widgetForm, list });
  emit('update:widgetFormSelect', list[newIndex]);
};

const handleColMoveAdd = (event: any, row: any, index: number) => {
  const { newIndex, oldIndex, item } = event;

  if (item?.className?.includes('data-grid')) {
    row.columns[index].list.splice(newIndex, 1);
    return false;
  }

  const key = uuidv4().replaceAll('-', '');
  const element = row.columns[index].list[newIndex];

  row.columns[index].list[newIndex] = {
    ...element,
    key,
    model: `${element.type}_${key}`,
    rules: []
  };

  if (['radio', 'checkbox', 'select'].includes(element.type)) {
    row.columns[index].list[newIndex].options.options = row.columns[index].list[newIndex].options.options.map((item: any) => ({
      ...item
    }));
  }

  emit('update:widgetFormSelect', row.columns[index].list[newIndex]);
};
</script>
